import type { Transform } from "jscodeshift";

import type { IdentifierRename } from "./renames.js";
import { handleIdentiferRename } from "./util/handleIdentiferRename.js";

// prettier-ignore
const removals = [
  { importType: "type", module: "@apollo/client", identifier: "ClientParseError" },
  { importType: "type", module: "@apollo/client", identifier: "FetchMoreQueryOptions" },
  { importType: "type", module: "@apollo/client", identifier: "FragmentMatcher" },
  { importType: "type", module: "@apollo/client", identifier: "MethodKeys" },
  { importType: "type", module: "@apollo/client", identifier: "MutationUpdaterFn" },
  { importType: "type", module: "@apollo/client", identifier: "PureQueryOptions" },
  { importType: "type", module: "@apollo/client", identifier: "Resolver" },
  { importType: "type", module: "@apollo/client", identifier: "Resolvers" },
  { importType: "type", module: "@apollo/client/errors", identifier: "ApolloErrorOptions" },
  { importType: "type", module: "@apollo/client/errors", identifier: "GraphQLErrors" },
  { importType: "type", module: "@apollo/client/errors", identifier: "NetworkError" },
  { importType: "type", module: "@apollo/client/link/batch", identifier: "BatchableRequest" },
  { importType: "type", module: "@apollo/client/link/http", identifier: "ClientParseError" },
  { importType: "type", module: "@apollo/client/masking", identifier: "Masked" },
  { importType: "type", module: "@apollo/client/masking", identifier: "MaskedDocumentNode" },
  { importType: "type", module: "@apollo/client/react", identifier: "BaseMutationOptions" },
  { importType: "type", module: "@apollo/client/react", identifier: "BaseQueryOptions" },
  { importType: "type", module: "@apollo/client/react", identifier: "CommonOptions" },
  { importType: "type", module: "@apollo/client/react", identifier: "IDocumentDefinition" },
  { importType: "type", module: "@apollo/client/react", identifier: "MutationDataOptions" },
  { importType: "type", module: "@apollo/client/react", identifier: "ObservableQueryFields" },
  { importType: "type", module: "@apollo/client/react", identifier: "QueryDataOptions" },
  { importType: "type", module: "@apollo/client/react", identifier: "QueryLazyOptions" },
  { importType: "type", module: "@apollo/client/react", identifier: "RefetchQueriesFunction" },
  { importType: "type", module: "@apollo/client/react", identifier: "SubscriptionCurrentObservable" },
  { importType: "type", module: "@apollo/client/react/components", identifier: "MutationComponentOptions" },
  { importType: "type", module: "@apollo/client/react/components", identifier: "QueryComponentOptions" },
  { importType: "type", module: "@apollo/client/react/components", identifier: "SubscriptionComponentOptions" },
  { importType: "type", module: "@apollo/client/react/context", identifier: "ApolloConsumerProps" },
  { importType: "type", module: "@apollo/client/react/hoc", identifier: "ChildDataProps" },
  { importType: "type", module: "@apollo/client/react/hoc", identifier: "ChildMutateProps" },
  { importType: "type", module: "@apollo/client/react/hoc", identifier: "ChildProps" },
  { importType: "type", module: "@apollo/client/react/hoc", identifier: "DataProps" },
  { importType: "type", module: "@apollo/client/react/hoc", identifier: "DataValue" },
  { importType: "type", module: "@apollo/client/react/hoc", identifier: "MutateProps" },
  { importType: "type", module: "@apollo/client/react/hoc", identifier: "OperationOption" },
  { importType: "type", module: "@apollo/client/react/hoc", identifier: "OptionProps" },
  { importType: "type", module: "@apollo/client/react/hoc", identifier: "QueryControls" },
  { importType: "type", module: "@apollo/client/react/hoc", identifier: "WithApolloClient" },
  { importType: "type", module: "@apollo/client/react/parser", identifier: "IDocumentDefinition" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "ConcastSourcesArray" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "ConcastSourcesIterable" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "DirectiveInfo" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "Directives" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "GetDirectiveConfig" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "GetFragmentSpreadConfig" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "GetNodeConfig" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "InclusionDirectives" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "IsStrictlyAny" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "OnlyRequiredProperties" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "PromiseWithState" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "ReconcilerFunction" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "RemoveArgumentsConfig" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "RemoveDirectiveConfig" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "RemoveFragmentDefinitionConfig" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "RemoveFragmentSpreadConfig" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "RemoveNodeConfig" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "RemoveVariableDefinitionConfig" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "TupleToIntersection" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "UnionToIntersection" },
  { importType: "type", module: "@apollo/client/utilities", identifier: "VariableValue" },
  { importType: "value", module: "@apollo/client", identifier: "ApolloError" },
  { importType: "value", module: "@apollo/client", identifier: "DataProxy" },
  { importType: "value", module: "@apollo/client", identifier: "fromError" },
  { importType: "value", module: "@apollo/client", identifier: "fromPromise" },
  { importType: "value", module: "@apollo/client", identifier: "isApolloError" },
  { importType: "value", module: "@apollo/client", identifier: "ObservableSubscription" },
  { importType: "value", module: "@apollo/client", identifier: "Observer" },
  { importType: "value", module: "@apollo/client", identifier: "serializeFetchParameter" },
  { importType: "value", module: "@apollo/client", identifier: "throwServerError" },
  { importType: "value", module: "@apollo/client", identifier: "toPromise" },
  { importType: "value", module: "@apollo/client/cache", identifier: "DataProxy" },
  { importType: "value", module: "@apollo/client/errors", identifier: "ApolloError" },
  { importType: "value", module: "@apollo/client/errors", identifier: "isApolloError" },
  { importType: "value", module: "@apollo/client/link/batch", identifier: "OperationBatcher" },
  { importType: "value", module: "@apollo/client/link/http", identifier: "serializeFetchParameter" },
  { importType: "value", module: "@apollo/client/link/utils", identifier: "fromError" },
  { importType: "value", module: "@apollo/client/link/utils", identifier: "fromPromise" },
  { importType: "value", module: "@apollo/client/link/utils", identifier: "throwServerError" },
  { importType: "value", module: "@apollo/client/link/utils", identifier: "toPromise" },
  { importType: "value", module: "@apollo/client/link/utils", identifier: "transformOperation" },
  { importType: "value", module: "@apollo/client/link/utils", identifier: "validateOperation" },
  { importType: "value", module: "@apollo/client/react", identifier: "ApolloConsumer" },
  { importType: "value", module: "@apollo/client/react", identifier: "DocumentType" },
  { importType: "value", module: "@apollo/client/react", identifier: "operationName" },
  { importType: "value", module: "@apollo/client/react", identifier: "parser" },
  { importType: "value", module: "@apollo/client/react", identifier: "resetApolloContext" },
  { importType: "value", module: "@apollo/client/react/components", identifier: "Mutation" },
  { importType: "value", module: "@apollo/client/react/components", identifier: "Query" },
  { importType: "value", module: "@apollo/client/react/components", identifier: "Subscription" },
  { importType: "value", module: "@apollo/client/react/context", identifier: "ApolloConsumer" },
  { importType: "value", module: "@apollo/client/react/context", identifier: "resetApolloContext" },
  { importType: "value", module: "@apollo/client/react/hoc", identifier: "graphql" },
  { importType: "value", module: "@apollo/client/react/hoc", identifier: "withApollo" },
  { importType: "value", module: "@apollo/client/react/hoc", identifier: "withMutation" },
  { importType: "value", module: "@apollo/client/react/hoc", identifier: "withQuery" },
  { importType: "value", module: "@apollo/client/react/hoc", identifier: "withSubscription" },
  { importType: "value", module: "@apollo/client/react/parser", identifier: "DocumentType" },
  { importType: "value", module: "@apollo/client/react/parser", identifier: "operationName" },
  { importType: "value", module: "@apollo/client/react/parser", identifier: "parser" },
  { importType: "value", module: "@apollo/client/react/parser", identifier: "verifyDocumentType" },
  { importType: "value", module: "@apollo/client/react/ssr", identifier: "RenderPromises" },
  { importType: "value", module: "@apollo/client/testing", identifier: "createMockClient" },
  { importType: "value", module: "@apollo/client/testing", identifier: "itAsync" },
  { importType: "value", module: "@apollo/client/testing", identifier: "mockObservableLink" },
  { importType: "value", module: "@apollo/client/testing", identifier: "mockSingleLink" },
  { importType: "value", module: "@apollo/client/testing", identifier: "subscribeAndCount" },
  { importType: "value", module: "@apollo/client/testing", identifier: "tick" },
  { importType: "value", module: "@apollo/client/testing", identifier: "wait" },
  { importType: "value", module: "@apollo/client/testing", identifier: "withErrorSpy" },
  { importType: "value", module: "@apollo/client/testing", identifier: "withLogSpy" },
  { importType: "value", module: "@apollo/client/testing", identifier: "withWarningSpy" },
  { importType: "value", module: "@apollo/client/testing/core", identifier: "createMockClient" },
  { importType: "value", module: "@apollo/client/testing/core", identifier: "itAsync" },
  { importType: "value", module: "@apollo/client/testing/core", identifier: "mockObservableLink" },
  { importType: "value", module: "@apollo/client/testing/core", identifier: "mockSingleLink" },
  { importType: "value", module: "@apollo/client/testing/core", identifier: "subscribeAndCount" },
  { importType: "value", module: "@apollo/client/testing/core", identifier: "tick" },
  { importType: "value", module: "@apollo/client/testing/core", identifier: "withErrorSpy" },
  { importType: "value", module: "@apollo/client/testing/core", identifier: "withLogSpy" },
  { importType: "value", module: "@apollo/client/testing/core", identifier: "withWarningSpy" },
  { importType: "value", module: "@apollo/client/testing/experimental", identifier: "createSchemaFetch" },
  { importType: "value", module: "@apollo/client/testing/experimental", identifier: "createTestSchema" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "addNonReactiveToNamedFragments" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "asyncMap" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "buildQueryFromSelectionSet" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "canUseAsyncIteratorSymbol" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "canUseLayoutEffect" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "canUseSymbol" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "canUseWeakMap" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "canUseWeakSet" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "Concast" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "defaultCacheSizes" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "fixObservableSubclass" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "getDirectiveNames" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "getFragmentMaskMode" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "getInclusionDirectives" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "getTypenameFromResult" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "hasAllDirectives" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "hasAnyDirectives" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "hasClientExports" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "isApolloPayloadResult" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "isExecutionPatchIncrementalResult" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "isExecutionPatchInitialResult" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "isExecutionPatchResult" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "isFullyUnmaskedOperation" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "isInlineFragment" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "isStatefulPromise" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "iterateObserversSafely" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "mergeIncrementalData" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "ObservableSubscription" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "Observer" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "removeArgumentsFromDocument" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "removeClientSetsFromDocument" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "removeConnectionDirectiveFromDocument" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "removeFragmentSpreadFromDocument" },
  { importType: "value", module: "@apollo/client/utilities", identifier: "valueToObjectRepresentation" },
] satisfies Array<{
  module: string;
  identifier: string;
  importType: "type" | "value";
}>;

const removalsTransform: Transform = function transform(file, api) {
  const j = api.jscodeshift;
  const source = j(file.source);
  const context = { j, source };

  let modified = false;
  for (const removal of removals) {
    const rename: IdentifierRename = {
      from: {
        module: removal.module,
        identifier: removal.identifier,
        alternativeModules: ["@apollo/client", "@apollo/client/core"],
      },
      to: { module: "@apollo/client/v4-migration", alternativeModules: [] },
      importType: removal.importType,
    };
    handleIdentiferRename({
      rename,
      context,
      onModify: () => {
        modified = true;
      },
    });
  }
  return modified ? source.toSource() : undefined;
};
export default removalsTransform;
